package com.wistech.search.solr.support;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.util.Assert;
import com.mongodb.DBAddress;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;

public class MongoFactoryBean implements InitializingBean, DisposableBean {
	private static final Logger logger = LoggerFactory
			.getLogger(MongoFactoryBean.class);
	public static final int DEFAULT_MONGO_POOL_SIZE = 10;
	/**
	 * Mongo对象
	 */
	private Mongo mongo;

	/**
	 * the database's name
	 */
	private String database;

	/**
	 * 连接mongodb的用户名
	 */
	private String username;

	/**
	 * 连接mongodb的密码
	 */
	private String password;
	/**
	 * number of connections allowed per host will block if run out,default is
	 * 10.
	 */
	public int connectionsPerHost = Integer.parseInt(System.getProperty(
			"MONGO.POOLSIZE", "10"));

	private String url;
	/**
	 * the database's host address
	 */
	private String host;
	/**
	 * the port on which the database is running
	 */
	private int port = 0;
	/**
	 * max wait time of a blocking thread for a connection
	 */
	private int maxWaitTime = 1000 * 60 * 2;
	/**
	 * connect timeout in milliseconds. 0 is default and infinite
	 */
	private int connectTimeout = 0;

	/**
	 * socket timeout. 0 is default and infinite
	 */
	private int socketTimeout = 0;

	/**
	 * this controls whether or not on a connect, the system retries
	 * automatically
	 */
	private boolean autoConnectRetry = false;

	private int threadsAllowedToBlockForConnectionMultiplier;

	public Mongo getMongo() {
		return this.mongo;
	}

	public String getDatabase() {
		return database;
	}

	public void setConnectionsPerHost(int connectionsPerHost) {
		this.connectionsPerHost = connectionsPerHost;
	}

	/**
	 * @param url
	 *            the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public void setPort(int port) {
		this.port = port;
	}

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	public void setMaxWaitTime(int maxWaitTime) {
		this.maxWaitTime = maxWaitTime;
	}

	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	public void setSocketTimeout(int socketTimeout) {
		this.socketTimeout = socketTimeout;
	}

	public void setAutoConnectRetry(boolean autoConnectRetry) {
		this.autoConnectRetry = autoConnectRetry;
	}

	/**
	 * @param threadsAllowedToBlockForConnectionMultiplier
	 *            the threadsAllowedToBlockForConnectionMultiplier to set
	 */
	public void setThreadsAllowedToBlockForConnectionMultiplier(
			int threadsAllowedToBlockForConnectionMultiplier) {
		this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
	}

	@Required
	public void setDatabase(String dbName) {
		this.database = dbName;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.isTrue(url != null || host != null,
				"You must special the mongodb address.");
		buildMongoFactory();
	}

	public void buildMongoFactory() throws UnknownHostException {
		logger.debug("Building mongodb factory.");
		List<ServerAddress> dbAddresses = new ArrayList<ServerAddress>();
		if (url != null) {
			String[] addresses = url.split(",");
			for (String address : addresses) {
				dbAddresses.add(new DBAddress(address));
			}
		} else {
			if (port == 0) {
				dbAddresses.add(new ServerAddress(host));
			} else {
				dbAddresses.add(new ServerAddress(host, port));
			}
		}
		MongoOptions options = new MongoOptions();
		options.connectionsPerHost = this.connectionsPerHost;
		options.connectTimeout = this.connectTimeout;
		options.maxWaitTime = this.maxWaitTime;
		options.socketTimeout = this.socketTimeout;
		options.autoConnectRetry = this.autoConnectRetry;
		options.threadsAllowedToBlockForConnectionMultiplier = this.threadsAllowedToBlockForConnectionMultiplier;
		logger.info("Building mongodb factory." + options);
		mongo = new Mongo(dbAddresses, options);
	}

	@Override
	public void destroy() throws Exception {
		mongo.close();
	}
}
